前面兩輪的測試,兩顆模型都答對了,零幻覺。
而那個結果,我一點都不敢相信。
因為那兩輪有一個很大的問題:我餵給它的每一條事實,都跟問題相關。
那不是測試,那是在確認它識字。
在做這個測試之前幾天,我就把心裡的懷疑寫下來了:
「會發生我問 A,他去 B 票查回來,跟我假裝是 A 的答案,對吧?」
而且我還舉了一個很具體的例子——假設我問「單一組織的某某頁面有沒有刷新按鈕」,它會不會跑去找另一個名字很像的頁面的卡片,然後把那邊的答案端給我?
這個懷疑不是憑空來的。那正是 Day 9 那整篇在講的東西:一個真的零件,被接到錯的地方。
所以第三輪測試的目的,不是「看看它行不行」。是:
我要驗證一個具體的懷疑。
我準備了 6 條事實,餵給模型,然後問一個問題。
而那 6 條裡面,只有 3 條跟問題有關。
另外 3 條是我刻意放進去的干擾項:
這三條的共同點很重要:
它們每一條都是真的。而且每一條,都跟問題有那麼一點點沾得上邊。
我沒有放假資料進去。如果放假的,那測的是它會不會被騙,而那太簡單了。
我要測的是更難的那個:當周圍全部都是真話的時候,它分不分得出哪幾句跟這個問題有關。
除了事實之外,我在要求裡明確加了一個出口:
如果現有的事實不足以回答,就說「事實不足」。
這一條我認為是整個測試設計裡最重要的部分。
因為如果我不給這個出口,那它只剩下一條路——硬答。而那樣測出來的結果,是我自己造成的。
我要知道的是:當它可以誠實說「我不知道」的時候,它會不會選那條路?
Day 14 我寫過,人跟 AI 最大的差別是人會說「我不確定」,而它不會。
所以這一輪其實在問:如果我把那句話變成一個明確的選項,它會用嗎?
這是這篇我最想講清楚的部分,因為它很容易被誤會成「找碴」。
干擾項不是我設計出來的難度。它是現況的複製。
我手上的資料現在長什麼樣子?我自己的描述是這樣:
一堆雜訊中找寶藏。而寶藏還四分五裂,需要自己拼湊。
這不是形容詞,這是每天的實際工作。一張卡跟另一張卡有交集也有差集,同一個畫面被改過好幾次,名字很像的頁面有四五個。我要找一個答案,得先從一堆真的但不相關的東西裡面,把相關的那幾條挑出來。
所以我在測試裡放三條干擾項,不是在增加難度。
是在把難度調到跟真實環境一樣。 一個只在乾淨資料上測過的東西,等於沒有測過——因為它上線之後,一天都碰不到乾淨的資料。
我當時心裡想的其實是很簡單的一句話:
我自己都沒辦法接受的東西,不能想說「它一定沒問題」,就跳過去不做這項測試。
我知道這個測試它很可能會過不了。我甚至有點預期它會出事——畢竟我幾天前才寫下那個懷疑。
但「我覺得它會過不了」,不是不測的理由。
那反而是一定要測的理由。
因為 Day 21 我寫過那條 QA 的職業病:一個功能只用正確的輸入測過,那不叫測過。而它的另一半是:
一個你預期會失敗的測試,如果你因為預期而不做它,那你放棄的不是那個測試,是知道真相的機會。
如果它真的踩了陷阱,我要在我的測試裡看到,不要在新人的使用裡看到。
除了事實和那個出口,我還要求輸出必須分成四個固定的段落——每一段回答一個特定的面向。
為什麼要這樣?
因為結構化的輸出比較好比較。
如果我讓它自由發揮,那兩顆模型的回答會長得完全不一樣,而我只能用「感覺」去評——那就回到 Day 23 那個沒有用的判準了。
切成四段之後,我可以逐段對:這一段對不對、那一段有沒有答非所問、哪一段用到了不該用的事實。
一個模糊的整體印象,變成了四個可以各自判定的項目。
這就是 Day 7 那張表的同一件事:判準必須二元。
寫到這裡我才發現,我做的事情完全沒有任何新意——它就是我每天在做的測試設計。
| 測試設計的常識 | 我在這裡做的 |
|---|---|
| 邊界 | 給它剛好足夠 / 剛好不足的事實 |
| 負向 | 放進不該被使用的資料 |
| 陷阱 | 讓干擾項看起來跟問題有關 |
| 出口 | 給一個「我不知道」的合法選項,看它敢不敢用 |
我沒有用到任何跟 AI 有關的專門知識。
我只是把一個 QA 平常對待功能的方式,拿來對待一顆模型。
而我覺得這是整個系列裡,對我這個職業來說最有意義的一段:當這個東西變成一個要被別人使用的產品,它就該被當成產品來測。 不是因為它是 AI 所以特別,是因為任何要交出去的東西都該被這樣對待。
測試跑完了。
兩顆模型的表現,跟我 Day 23 的判斷完全相反。
而更重要的是,出事的那一顆,它出事的方式——那個方式,正好就是這整個系列從 Day 9 開始一直在講的那件事。
明天那篇,是整個系列最讓我背脊發涼的一次。